
import { arrayMethods } from './array';
import {def} from '../util';
import Dep from './dep';
// 处理响应式
class Observer {
    constructor(value) {
        // 为数组收集依赖，并且对象的$set的时候能更新...
        this.dep = new Dep();
        this.value = value;
        // 让value.__ob__不可遍历，否则走到walk就会循环引用，栈溢出
        def(value, "__ob__", this);
        // 处理数组
        if (Array.isArray(value)) {
            // 需要重写数组的方法
            value.__proto__ = arrayMethods;
            // 如果数组内有对象，那么对对象也要响应式处理
            this.observeArray(value);
        } else {
            this.walk(value);
        }
    }
    walk(obj) {
        for (let prop in obj) {
            defineReactive(prop, obj[prop], obj)
        }
    }
    observeArray(arr) {
        const len = arr.length;
        for (let i = 0; i < len; i++) {
            observe(arr[i]);
        }
    }
}

// 1 深层递归
// 2 赋值是对象也要变成响应式
export function defineReactive(key, value, obj) {
    // 每个key都有一个dep
    const dep = new Dep();
    // value是对象，会返回这个value的Observer实例
    let childOb = observe(value);
    Object.defineProperty(obj, key, {
        get() {
            // 收集依赖
            if (Dep.target) { // render函数中，开始从模板获取数据
                dep.depend();
                if (childOb) { // 为数组或对象本身收集依赖 {arr: [1, 2, 3], obj: {a: 11, b: 22}}
                    childOb.dep.depend();
                    if (Array.isArray(value)) {
                        // 如果数组本身还有数组，那么将子数组进行依赖收集，只有对象能进来，所以只能在最外层数组把所有的数组进行依赖收集
                        dependArray(value);
                    }
                }
            }
            return value;
        },
        set(newValue) {
            if (newValue !== value) {
                // 设置值如果是对象，也要响应式处理
                observe(newValue);
                value = newValue
                dep.notify();
                // 触发更新
            }
        }
    })
}
function dependArray(arr) {
    for (let i = 0; i < arr.length; i++) {
        let ob = arr[i];
        ob.__ob__ && ob.__ob__.dep.depend();
        if (Array.isArray(ob)) {
            dependArray(ob);
        }
    }
}

export function observe(value) {
    if (value == null || typeof value !== 'object') {
        return;
    }
    // 该对象已经观测过了，直接返回
    if (value.__ob__) {
        return value.__ob__;
    }
    return new Observer(value);
}



